﻿using System;
using System.Collections.Generic;
using System.Linq;
using MIAP.DataAccess.Interfaces;
using MIAP.Entidades;

namespace MIAP.Negocio
{
    /// <summary>
    /// Clase de negocio para las operaciones de SolicitudRecarga.
    /// </summary>
    public class SolicitudRecargaNegocio
    {
        #region Campos

        /// <summary>
        /// Instancia para el acceso a datos de Solicitud de recargas de archivos.
        /// </summary>
        private readonly ISolicitudRecargaArchivoDao daoSolicitud;

        /// <summary>
        /// Instancia para el acceso a las operaciones de negocio comunes.
        /// </summary>
        private ComunesNegocio comunesNegocio;

        #endregion

        #region Constructor

        /// <summary>
        /// Inicializa una instancia de <see cref="SolicitudRecargaNegocio"/>
        /// </summary>
        public SolicitudRecargaNegocio()
        {
            this.daoSolicitud = DataAccessFactory.Instance.CreateSolicitudRecargasDao();
            this.comunesNegocio = new ComunesNegocio();
        }

        #endregion

        #region Metodos

        /// <summary>
        /// Obtiene todos los archivos que el usuario pueda cargar. 
        /// </summary>
        /// <param name="idProyecto">Es el id del proyecto con el que deberán estar relacionados los archivos.</param>
        /// <param name="idUsuario">Es el id del usuario con el cual deberán estar relacionados los archivos.</param>
        /// <returns>Lista de archivos.</returns>
        public List<CatalogoInfo> GetArchivosByUsuarioProyecto(int idProyecto, int? idUsuario)
        {
            var retorno = this.daoSolicitud.GetArchivosByUsuarioProyecto(idProyecto, idUsuario).ToList();
            //obtenemos la lista sin objetos repetidos
            var lista = new List<CatalogoInfo>();
            foreach (var catalogo in retorno.Where(catalogo => !lista.Any(elemento => elemento.Equals(catalogo))))
            {
                lista.Add(catalogo);
            }
            return lista;
        }

        /// <summary>
        /// Obtiene los archivos relacionados con el usuario a los que se les puede levantar una solicitud de recarga.
        /// </summary>
        /// <param name="filtroSolicitud">Filtros aplicados a la consulta.</param>
        /// <returns>Lista de archivos</returns>
        public List<SolicitudRecargaArchivoInfo> GetArchivosRecarga(SolicitudRecargaArchivoInfo filtroSolicitud)
        {
            List<SolicitudRecargaArchivoInfo> listArchivos = this.daoSolicitud.GetArchivosRecarga(filtroSolicitud).ToList();

            // Obtener los archivos recargables con el último proceso por cada versión.
            List<SolicitudRecargaArchivoInfo> listArchivosRecargables = ComunesNegocio.GetArchivoWithLastProcess(listArchivos);

                List<CatalogoInfo> listVersionesArchivo = this.daoSolicitud.GetVersionArchivoEnSolicitud().ToList();

                // Remueve los archivos que ya cuentan con una solicitud en estatus pendiente o autorizada.
                foreach (CatalogoInfo versionArchivo in listVersionesArchivo)
                {
                    SolicitudRecargaArchivoInfo archivoRecargable =
                        listArchivosRecargables.Where(p => p.IdArchivo == versionArchivo.IdItem && p.Version == versionArchivo.Descripcion)
                                               .SingleOrDefault();

                    if (archivoRecargable != null)
                    {
                        listArchivosRecargables.Remove(archivoRecargable);
                    }
                }
            
            List<CatalogoInfo> listArchivosRecarga = new List<CatalogoInfo>();
            List<EjecutorInfo> listUsuariosVersionadores = new List<EjecutorInfo>();

            foreach (SolicitudRecargaArchivoInfo archivo in listArchivosRecargables)
            {
                listArchivosRecarga.Add(new CatalogoInfo { IdItem = archivo.IdCargaArchivo, Descripcion = archivo.Version });
                listUsuariosVersionadores.Add(new EjecutorInfo() { IdArchivo = archivo.IdArchivo.Value, VersionArchivo = archivo.Version, UsuarioEjecutor = archivo.NombreEjecutorCarga });
            }

            if (listArchivosRecarga.Count != default(int))
            {
                // Obtener los autorizadores.
                List<EjecutorInfo> listAutorizadores = this.comunesNegocio.GetAutorizador(listArchivosRecarga).ToList();


                foreach (EjecutorInfo autorizador in listAutorizadores)
                {
                    listArchivosRecargables.Where(p => p.IdCargaArchivo == autorizador.IdCargaArchivo && p.Version == autorizador.VersionArchivo).Single().Autorizador = autorizador.NombreEjecutor;
                }

                // Obtener el nombre del ejecutor de la carga del archivo.
                List<EjecutorInfo> listEjecutoresCarga = this.daoSolicitud.GetNombreVersionador(listUsuariosVersionadores).ToList();

                foreach (EjecutorInfo ejecutorCarga in listEjecutoresCarga)
                {
                    listArchivosRecargables.Where(p => p.IdArchivo == ejecutorCarga.IdArchivo && p.NombreEjecutorCarga == ejecutorCarga.UsuarioEjecutor && p.Version == ejecutorCarga.VersionArchivo).Single().NombreEjecutorCarga = ejecutorCarga.NombreEjecutor;
                }
            }

            return listArchivosRecargables;
        }

        /// <summary>
        /// Guarda una solicitud de recarga de archivo.
        /// </summary>
        /// <param name="solicitud">Solicitud que será guardada.</param>
        /// <param name="user">Usuario que ejecuta la operación.</param>
        public void AddSolicitudRecarga(SolicitudRecargaArchivoInfo solicitud, string user)
        {
            this.daoSolicitud.AddSolicitudRecarga(solicitud, user);
        }

        /// <summary>
        /// Obtiene las direcciones de correo de los autorizadores de archivo.
        /// </summary>
        /// <param name="idArchivo">Es el id del archivo.</param>
        /// <returns>Lista de direcciones de correo de los autorizadores del archivo.</returns>
        public List<string> GetCorreosAutorizadoresByArchivo(int idArchivo)
        {
            return this.daoSolicitud.GetCorreosAutorizadoresByArchivo(idArchivo).ToList();
        }

        #endregion
    }
}
